<template>
  <div class="suspense-transition-demo">
    <h2>Suspense 和 Transition 动画</h2>
    
    <!-- 介绍部分 -->
    <div class="introduction">
      <p>Suspense 用于处理异步组件的加载状态，而 Transition 提供了组件进入/离开的动画效果。</p>
    </div>

    <!-- 1. Suspense 演示 -->
    <section class="demo-section">
      <h3>1. Suspense 异步组件加载</h3>
      <div class="demo-controls">
        <button @click="toggleAsyncComponent" class="btn">
          {{ showAsync ? '隐藏异步组件' : '显示异步组件' }}
        </button>
      </div>
      
      <div class="suspense-container">
        <Transition name="fade" mode="out-in">
          <Suspense v-if="showAsync" :key="componentKey">
            <template #default>
              <AsyncComponent :delay="delay" />
            </template>
            <template #fallback>
              <div class="loading">
                <div class="spinner"></div>
                <p>加载中...</p>
              </div>
            </template>
          </Suspense>
        </Transition>
      </div>

      <div class="control-group">
        <label>加载延迟 (ms):</label>
        <input type="range" v-model.number="delay" min="500" max="3000" step="100">
        <span>{{ delay }}ms</span>
      </div>
    </section>

    <!-- 2. Transition 动画演示 -->
    <section class="demo-section">
      <h3>2. Transition 组件动画</h3>
      <div class="demo-controls">
        <button @click="showElement = !showElement" class="btn">
          {{ showElement ? '隐藏元素' : '显示元素' }}
        </button>
        <select v-model="animationType" class="select">
          <option value="fade">淡入淡出</option>
          <option value="slide">滑动</option>
          <option value="scale">缩放</option>
          <option value="bounce">弹跳</option>
        </select>
      </div>
      
      <Transition :name="animationType" appear>
        <div v-if="showElement" :key="elementKey" class="animated-element">
          <p>这是一个带动画的元素</p>
        </div>
      </Transition>
    </section>

    <!-- 3. TransitionGroup 列表动画 -->
    <section class="demo-section">
      <h3>3. TransitionGroup 列表动画</h3>
      <div class="demo-controls">
        <button @click="addItem" class="btn">添加项目</button>
        <button @click="removeItem" class="btn btn-danger">移除项目</button>
        <button @click="shuffleItems" class="btn btn-secondary">打乱顺序</button>
      </div>
      
      <TransitionGroup name="list" tag="ul" class="item-list">
        <li v-for="(item, index) in items" :key="item.id" class="list-item">
          {{ item.content }} (ID: {{ item.id }})
        </li>
      </TransitionGroup>
    </section>

    <!-- 4. 实际应用场景 -->
    <section class="demo-section">
      <h3>4. 实际应用场景：页面切换动画</h3>
      <div class="demo-controls">
        <button @click="currentPage = 1" class="btn" :class="{ active: currentPage === 1 }">
          页面 1
        </button>
        <button @click="currentPage = 2" class="btn" :class="{ active: currentPage === 2 }">
          页面 2
        </button>
        <button @click="currentPage = 3" class="btn" :class="{ active: currentPage === 3 }">
          页面 3
        </button>
      </div>
      
      <div class="pages-container">
        <Transition name="page" mode="out-in">
          <div :key="currentPage" class="page">
            <h4>页面 {{ currentPage }}</h4>
            <p>这是第 {{ currentPage }} 个页面的内容。</p>
            <div class="page-content">
              <img v-if="currentPage === 1" :src="vueLogo" alt="Vue Logo" class="logo">
              <div v-else-if="currentPage === 2" class="feature-list">
                <div class="feature-item">特性 A</div>
                <div class="feature-item">特性 B</div>
                <div class="feature-item">特性 C</div>
              </div>
              <div v-else-if="currentPage === 3" class="stats">
                <div class="stat-item">完成度: 85%</div>
                <div class="stat-item">性能: 92/100</div>
                <div class="stat-item">用户体验: 优秀</div>
              </div>
            </div>
          </div>
        </Transition>
      </div>
    </section>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import vueLogo from '@assets/vue.svg';

// 异步组件模拟
const AsyncComponent = {}
// 动态导入异步组件
const loadAsyncComponent = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        template: `
          <div class="async-content">
            <h4>异步加载的组件</h4>
            <p>这是一个使用 Suspense 加载的异步组件</p>
            <p>加载延迟: {{ delay }}ms</p>
          </div>
        `,
        props: ['delay']
      })
    }, 100)
  })
}

// Suspense 相关状态
const showAsync = ref(false)
const componentKey = ref(0)
const delay = ref(1000)

// Transition 相关状态
const showElement = ref(false)
const animationType = ref('fade')
const elementKey = ref(0)

// TransitionGroup 相关状态
const items = ref([
  { id: 1, content: '项目 1' },
  { id: 2, content: '项目 2' },
  { id: 3, content: '项目 3' }
])
let nextId = 4

// 页面切换相关状态
const currentPage = ref(1)

// 方法
const toggleAsyncComponent = async () => {
  showAsync.value = !showAsync.value
  if (showAsync.value) {
    // 重新加载组件以展示加载状态
    componentKey.value++
    // 动态导入组件
    AsyncComponent.__asyncLoader = () => loadAsyncComponent()
  }
}

const addItem = () => {
  items.value.push({ id: nextId++, content: `项目 ${items.value.length + 1}` })
}

const removeItem = () => {
  if (items.value.length > 0) {
    items.value.splice(Math.floor(Math.random() * items.value.length), 1)
  }
}

const shuffleItems = () => {
  // Fisher-Yates shuffle
  const newItems = [...items.value]
  for (let i = newItems.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1))
    ;[newItems[i], newItems[j]] = [newItems[j], newItems[i]]
  }
  items.value = newItems
}
</script>

<style scoped>
.suspense-transition-demo {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

h2 {
  color: #333;
  margin-bottom: 30px;
  text-align: center;
}

.introduction {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 30px;
}

.demo-section {
  background-color: #fff;
  border-radius: 12px;
  padding: 24px;
  margin-bottom: 30px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

h3 {
  color: #42b983;
  margin-bottom: 20px;
  border-bottom: 2px solid #42b983;
  padding-bottom: 10px;
}

.demo-controls {
  display: flex;
  gap: 12px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.btn {
  background-color: #42b983;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.btn:hover {
  background-color: #3aa876;
}

.btn-danger {
  background-color: #e74c3c;
}

.btn-danger:hover {
  background-color: #c0392b;
}

.btn-secondary {
  background-color: #95a5a6;
}

.btn-secondary:hover {
  background-color: #7f8c8d;
}

.btn.active {
  background-color: #2c3e50;
}

.select {
  padding: 8px;
  border-radius: 6px;
  border: 1px solid #ddd;
}

.control-group {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 15px;
}

.control-group input[type="range"] {
  flex: 1;
  max-width: 300px;
}

/* Suspense 相关样式 */
.suspense-container {
  min-height: 200px;
  border: 2px dashed #ccc;
  border-radius: 8px;
  padding: 20px;
  margin: 20px 0;
  background-color: #f8f9fa;
}

.async-content {
  background-color: #e3f2fd;
  padding: 20px;
  border-radius: 8px;
  text-align: center;
}

.loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 150px;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #42b983;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 10px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* Transition 动画样式 */
.animated-element {
  background-color: #ff9800;
  color: white;
  padding: 30px;
  border-radius: 8px;
  text-align: center;
  margin: 20px 0;
}

/* 淡入淡出 */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* 滑动 */
.slide-enter-active,
.slide-leave-active {
  transition: all 0.3s ease;
}

.slide-enter-from {
  transform: translateX(-100%);
}

.slide-leave-to {
  transform: translateX(100%);
}

/* 缩放 */
.scale-enter-active,
.scale-leave-active {
  transition: all 0.3s ease;
}

.scale-enter-from,
.scale-leave-to {
  transform: scale(0);
}

/* 弹跳 */
.bounce-enter-active {
  animation: bounce-in 0.5s;
}

.bounce-leave-active {
  animation: bounce-in 0.5s reverse;
}

@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}

/* TransitionGroup 样式 */
.item-list {
  list-style: none;
  padding: 0;
  margin: 20px 0;
}

.list-item {
  background-color: #4285f4;
  color: white;
  padding: 15px;
  margin-bottom: 10px;
  border-radius: 6px;
  transition: all 0.3s ease;
}

.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}

.list-enter-from {
  opacity: 0;
  transform: translateX(-30px);
}

.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

.list-move {
  transition: transform 0.5s ease;
}

/* 页面切换样式 */
.pages-container {
  background-color: #f8f9fa;
  border-radius: 8px;
  min-height: 300px;
  overflow: hidden;
  position: relative;
}

.page {
  padding: 30px;
  text-align: center;
}

.page h4 {
  color: #333;
  margin-bottom: 20px;
}

.page-content {
  margin-top: 30px;
}

.logo {
  max-width: 200px;
  animation: float 3s ease-in-out infinite;
}

@keyframes float {
  0% {
    transform: translateY(0px);
  }
  50% {
    transform: translateY(-10px);
  }
  100% {
    transform: translateY(0px);
  }
}

.feature-list {
  display: flex;
  justify-content: center;
  gap: 20px;
  flex-wrap: wrap;
}

.feature-item {
  background-color: #9c27b0;
  color: white;
  padding: 20px 30px;
  border-radius: 8px;
  font-weight: bold;
}

.stats {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
}

.stat-item {
  background-color: #2196f3;
  color: white;
  padding: 15px 30px;
  border-radius: 25px;
  font-weight: bold;
  min-width: 200px;
}

/* 页面切换动画 */
.page-enter-active,
.page-leave-active {
  transition: all 0.4s ease;
}

.page-enter-from {
  opacity: 0;
  transform: translateX(20px);
}

.page-leave-to {
  opacity: 0;
  transform: translateX(-20px);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .demo-controls {
    flex-direction: column;
  }
  
  .btn {
    width: 100%;
  }
  
  .feature-list {
    flex-direction: column;
    align-items: center;
  }
  
  .feature-item {
    width: 100%;
    max-width: 250px;
  }
}
</style>